// 同一个文件不会被包含多次
#pragma once

#include <list>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <iostream>

// 队列层
template <typename T>
class TaskQueue
{
public:
    TaskQueue(int maxsize) : m_maxSize(maxsize), m_needStop(false) {}
    ~TaskQueue() {}

    // 添加事件,左值拷贝，右值移动
    void Put(const T &x)
    {
        Add(x);
    }
    void Put(T &&x)
    {
        Add(x);
    }

    // 从队列中取事件，取所有事件
    void Take(std::list<T> &list)
    {
        std::unique_lock<std::mutex> locker(m_mutex);
        // 满足条件则唤醒 不满足就阻塞
        m_notEmpty.wait(locker, [this]()
                        { return m_needStop || NotEmpty(); });
        if (m_needStop)
        {
            return;
        }
        list = std::move(m_queue);
        // 唤醒其他阻塞的线程
        m_notFull.notify_one();
    }

    void Take(T &t)
    {
        std::unique_lock<std::mutex> locker(m_mutex);
        m_notEmpty.wait(locker, [this]()
                        { return m_needStop || NotEmpty(); });
        if (m_needStop)
        {
            return;
        }

        t = m_queue.front();
        m_queue.pop_front();
        m_notFull.notify_one();
        t();
    }

    // 停止所有线程在队列中读取
    void Stop()
    {
        {
            std::lock_guard<std::mutex> locker(m_mutex);
            m_needStop = true;
        }
        m_notFull.notify_all();
        m_notEmpty.notify_all();
    }

    // 队列为空
    bool Empty()
    {
        std::lock_guard<std::mutex> locker(m_mutex);
        return m_queue.empty();
    }

    // 队列为满
    bool Full()
    {
        std::lock_guard<std::mutex> locker(m_mutex);
        return m_queue.size() == m_maxSize;
    }

    // 队列大小
    size_t Size()
    {
        std::lock_guard<std::mutex> locker(m_mutex);
        return m_queue.size();
    }

private:
    // 往队列里添加事件，事件是泛型的，通过std::function封装为对象
    template <typename F>
    void Add(F &&x)
    {
        std::unique_lock<std::mutex> locker(m_mutex);
        m_notFull.wait(locker, [this]()
                       { return m_needStop || NotFull(); });
        if (m_needStop)
        {
            return;
        }
        m_queue.push_back(std::forward<F>(x));
        m_notEmpty.notify_one();
    }

    // 队列未满
    bool NotFull() const
    {
        bool full = m_queue.size() >= m_maxSize;
        if (full)
        {
            std::cout << "queue is full" << std::endl;
        }
        return !full;
    }

    // 队列未空
    bool NotEmpty() const
    {
        bool empty = m_queue.empty();
        if (empty)
        {
            std::cout << "queue is empty...wait" << std::endl;
            std::cout << "thread id:" << std::this_thread::get_id() << std::endl;
        }
        return !empty;
    }

private:
    std::mutex m_mutex;                 // 互斥锁
    std::list<T> m_queue;               // 任务队列
    std::condition_variable m_notEmpty; // 队列不为空条件变量
    std::condition_variable m_notFull;  // 队列不为满条件变量
    int m_maxSize;                      // 任务最大长度
    bool m_needStop;                    // 终止标识
};